TrackControl
TrackControl Highlight control while button is down; get result
#include <Controls.h> Control Manager
short TrackControl( theControl, localPt, actionProc );
ControlHandle theControl ; control to track (from FindControl)
Point localPt ; point, in local coordinates of mouse-down
ProcPtr actionProc ; address of tracking hook proc; NIL= standard
returns a part code; 0= control not selected
TrackControl should be called after a mouse-down event occurs in an
active, visible control. The control is tracked as long as the button is held
down. Execution returns to the caller when the button is released. The return
value indicates whether or not the mouse was inside the control when the
mouse was released.
theControl specifies which control to track. It is normally the value obtained
from FindControl.
localPt is a 4-byte Point structure, expressed in local ( window)
coordinates. It is normally the local equivalent of the where field of
an EventRecord obtained via WaitNextEvent; i.e., the value used in
the previous call to FindControl.
actionProc lets you take additional, repeated action while the mouse is tracking
the control. It is one of:
NIL (0) The default tracking procedure is employed. NO additional
action is taken (use this for standard buttons and for tracking
the thumb of a scroll bar).
(-1) If (* theControl)->contrlAction is not NIL, a custom tracking
routine is called (see SetCtlAction).
an address (>0) The function at that address is called repeatedly as long as the
mouse is held down (this is often used for scrollbar paging and
scrolling-see below).
Returns: a short specifying the result of the tracking operation. It will be
one of:
0 The user had a change of heart and moved the mouse outside of
the control before releasing it.
a part code The user selected the control by releasing the button while
still inside of it. This identifies which part of the control was
selected; e.g., inButton.

Notes: TrackControl will always return 0 for a 'CDEF' that implements custom
dragging. To work around this problem, you can check the control's value
before and after the call to TrackControl.
The normal sequence after detecting a mouse-down event is to call
FindWindow, FindControl, and then TrackControl.
Normal Operation for Buttons: TrackControl highlights the button,
and continues to track the mouse until the button is released, unhighlighting
and rehighlighting as the mouse is moved out of, and back into the button. A
return result of 0 indicates the user changed had a change of heart about
pressing the button.
Normal Operation for Dials: TrackControl highlights (or grays)
the indicator (the part of the dial to be tracked; e.g., the thumb of a scroll
bar), and repeatedly calls the control's default tracking procedure until the
indicator is released. The tracking procedure redraws the part of the
control being tracked and updates the contrlValue field of the ControlRecord.
Customization Options: For standard buttons, and for the thumb of a
standard scroll bar, there is no reason to customize. A typical sequence is:
ctlPart = FindControl( mousePt, theWindow, & theControl);
if (ctlPart == inButton) {
if ( TrackControl( theControl, mousePt, 0) != 0 ) {
. . . do what's expected for selecting the button . . .
}
} . . . etc . . .
Scroll bars, on the other hand, DO require a custom actionProc to get them
to behave as expected. While pressing in a scroll arrow or paging area, the
user expects the screen to be updated immediately and repeatedly. To handle
this operation, use the following as a template for an actionProc :
/* ---- Use this for parts other than a dial indicator ----*/
pascal void myScrollAction( theControl, ctrlPart )
ControlHandle theControl;
short ctlPart; /* 0 when tracked outside */
{
... take action, depending upon the ctlPart parameter.
e.g., scroll the screen one notch or redraw the page.
If ctlPart is 0, the mouse is outside of the control ...
}
And specify the address of this function in the call:
ctlPart = FindControl( mousePt, theWindow, &theControl );
if ( ctlPart == inPageUp ) {
rc = TrackControl( theControl, mousePt, &myScrollAction );
} ... etc ...
For custom controls, you may need to use a custom tracking routine for the
indicator of a dial; your actionProc must expect NO parameters. Example:
/*---- Use this for custom dial indicators ----*/
pascal void myAction( void ) /* note: no parameters */
{
... Use TestControl to see if a point is in a control.
(Hint: intercept DragHook. See DragGrayRgn) ...
}
Finally, you can install your routine as the default tracking procedure by
storing its address in the contrlAction field of the ControlRecord (see
SetCtlAction). That routine will be called before (or in lieu of)
actionProc. See Custom Controls for information about designing your
own controls.